package com.xyht.sca_s.student_manage_system.modules.carUseManage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.Resp.*;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.SmsCarUseApplication;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.SmsCarUseApplicationDetail;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.SmsCarUseApplicationProcess;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.SmsCarWarehousing;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.entity.req.*;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.carUseManage.service.SmsCarUseApplicationService;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.carUseManage.constant.carStatusConstant.CAR_STATUS_IN;
import static com.xyht.sca_s.student_manage_system.modules.carUseManage.constant.carUseApplicationStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.carUseManage.constant.carUseApplicationTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.carUseManage.constant.carUseObjectTypeConstant.CAR_USE_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.carUseManage.constant.carUseObjectTypeConstant.CAR_USE_OBJECT_TYPE_ROLE;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-07-31
 */
@Service
public class SmsCarUseApplicationServiceImpl extends ServiceImpl<SmsCarUseApplicationMapper, SmsCarUseApplication> implements SmsCarUseApplicationService {
    @Autowired
    SmsCarUseApplicationMapper smsCarUseApplicationMapper;
    @Autowired
    SmsCarUseApplicationProcessMapper smsCarUseApplicationProcessMapper;
    @Autowired
    SmsCarUseApplicationDetailMapper smsCarUseApplicationDetailMapper;
    @Autowired
    NewTipsUtil newTipsUtil;
    @Autowired
    SmsCarWarehousingMapper smsCarWarehousingMapper;
    @Autowired
    CacheUtil cacheUtil;
    @Autowired
    SmsCarUseApplicationMpjMapper smsCarUseApplicationMpjMapper;
    @Autowired
    SmsUserMapper smsUserMapper;
    @Autowired
    SmsRoleMapper smsRoleMapper;

    @Transactional
    @Override
    public ResponseResult addApplication(SmsCarUseApplicationReq applicationReq, String userId) {
        //校验是否提交车辆id
        if(isNullOrEmpty(applicationReq.getCarId())){
            return CommonResult.failed(CommonCodeEnum.CAR_USE_NOT_CHOOSE);
        }
        //校验申请开始时间和结束时间是否合理
        if(applicationReq.getUseStartTime().compareTo(applicationReq.getUseEndTime())>=0||
                applicationReq.getUseStartTime().compareTo(new Date())<0){
            return CommonResult.failed(CommonCodeEnum.CAR_USE_TIME_ILLEGAL);
        }


        List<SmsCarUseApplicationProcess> fillProcessList =
                smsCarUseApplicationProcessMapper.selectList(new QueryWrapper<SmsCarUseApplicationProcess>()
                        .lambda()
                        .eq(SmsCarUseApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsCarUseApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsCarUseApplicationProcess::getProcessSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (applicationReq.getProcessList() == null || applicationReq.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsCarUseApplicationProcess> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<String> result = applicationReq.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                                        .map(SmsCarUseApplicationDetailReq::getId)
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                if (result.size() > 0) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_PROCESS_NOT_FILL);
            }
        }

        QueryWrapper<SmsCarWarehousing> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsCarWarehousing::getCarStatus, CAR_STATUS_IN)
                .eq(SmsCarWarehousing::getIsDeleted, 0);
        List<SmsCarWarehousing> list = smsCarWarehousingMapper.selectList(queryWrapper);
        if (isNullOrEmpty(list) && list.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.CAR_USE_APPLICATION_FAIL);
        }
        //创建申请表
        SmsCarUseApplication smsCarUseApplication = new SmsCarUseApplication();
        BeanUtils.copyProperties(applicationReq, smsCarUseApplication);
        QueryWrapper<SmsCarWarehousing> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SmsCarWarehousing::getId,smsCarUseApplication.getCarId());
        SmsCarWarehousing warehousing = smsCarWarehousingMapper.selectOne(wrapper);
        if(isNullOrEmpty(warehousing)){
            return CommonResult.failed(CommonCodeEnum.DATA_NOT_FOUND);
        }
        smsCarUseApplication.setCarPic(warehousing.getCarPic());
        smsCarUseApplication.setCarName(warehousing.getCarName());
        smsCarUseApplication.setCarPosition(warehousing.getCarPosition());
        smsCarUseApplication.setCarNum(warehousing.getCarNum());
        smsCarUseApplication.setApplyUserId(userId);
        smsCarUseApplication.setAllowStatus(CAR_USE_STATUS_WAIT_ALLOW);
        smsCarUseApplicationMapper.insert(smsCarUseApplication);

        if (smsCarUseApplication.getId() == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String application_id = smsCarUseApplication.getId();

        //创建审批流程
        List<SmsCarUseApplicationProcess> originProcessList =
                smsCarUseApplicationProcessMapper.selectList(new QueryWrapper<SmsCarUseApplicationProcess>()
                        .lambda()
                        .eq(SmsCarUseApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsCarUseApplicationProcess::getProcessSort));
        if (originProcessList == null || originProcessList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.CAR_USE_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsCarUseApplicationProcess process : originProcessList) {
            //判断管理员是否配置初始流程
            if (!process.getProcessIsApplicationEdit()) {
                if (isNullOrEmpty(process.getProcessObjectId()) || isNullOrEmpty(process.getProcessObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.CAR_USE_PROCESS_NOT_SETTING));
                }
            }

            SmsCarUseApplicationDetail addDetail =
                    new SmsCarUseApplicationDetail();

            addDetail.setApplicationId(application_id);
            addDetail.setProcessId(process.getId());
            addDetail.setProcessIsSign(process.getProcessIsSign());
            addDetail.setProcessIsStamp(process.getProcessIsStamp());
            addDetail.setProcessName(process.getProcessName());
            addDetail.setDetailAllowStatus(CAR_USE_STATUS_WAIT_ALLOW);

            addDetail.setDetailSort(sort++);


            //申请人可编辑流程
            if (process.getProcessIsApplicationEdit()) {
                List<SmsCarUseApplicationDetailReq> filterList = applicationReq.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_PROCESS_NOT_FILL));
                }
                SmsCarUseApplicationDetailReq fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessObjectId(fillProcessReq.getProcessObjectId());
                addDetail.setProcessObjectType(fillProcessReq.getProcessObjectType());
            } else {
                addDetail.setProcessObjectId(process.getProcessObjectId());
                addDetail.setProcessObjectType(process.getProcessObjectType());
            }
            smsCarUseApplicationDetailMapper.insert(addDetail);
        }
        //消息通知
        //通知流程第一个节点
        SmsCarUseApplicationDetail firstDetail =
                smsCarUseApplicationDetailMapper.selectOne(new QueryWrapper<SmsCarUseApplicationDetail>()
                        .lambda()
                        .eq(SmsCarUseApplicationDetail::getApplicationId, application_id)
                        .eq(SmsCarUseApplicationDetail::getDetailSort, 1)
                        .orderByAsc(SmsCarUseApplicationDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessIsApplicationEdit().equals(1)) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            if (firstDetail.getProcessObjectType() == CAR_USE_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }

        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessObjectId());
        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                userId,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_CAR_USE,
                application_id,
                firstDetail.getId());
        return CommonResult.success();
    }

    @Transactional
    @Override
    public ResponseResult cancelApplication(SmsCarUseApplicationCancelReq cancelReq, String userId) {
        if (isNullOrEmpty(cancelReq.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //查看审批表是否存在且是否为本人
        SmsCarUseApplication application =
                smsCarUseApplicationMapper.selectOne(new QueryWrapper<SmsCarUseApplication>()
                        .lambda()
                        .eq(SmsCarUseApplication::getId, cancelReq.getApplyId())
                        .eq(SmsCarUseApplication::getApplyUserId, userId));
        if (application == null || isNullOrEmpty(application.getId())) {
            return CommonResult.failed(CommonCodeEnum.CAR_USE_NOT_EXIST);
        }
        if (application.getAllowStatus() != CAR_USE_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.CAR_USE_CANCEL_FAIL_ALLOWED);
        }


        //撤回审批
        SmsCarUseApplication cancelApplication = new SmsCarUseApplication();
        cancelApplication.setId(cancelReq.getApplyId());
        cancelApplication.setAllowStatus(CAR_USE_STATUS_CANCEL);
        cancelApplication.setEndTime(new Date());
        smsCarUseApplicationMapper.updateById(cancelApplication);

        //修改节点状态
        SmsCarUseApplicationDetail cancelApplicationDetail = new SmsCarUseApplicationDetail();
        cancelApplicationDetail.setDetailAllowStatus(CAR_USE_STATUS_CANCEL);

        smsCarUseApplicationDetailMapper.update(cancelApplicationDetail, new QueryWrapper<SmsCarUseApplicationDetail>()
                .lambda()
                .eq(SmsCarUseApplicationDetail::getApplicationId, cancelReq.getApplyId())
                .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(cancelReq.getApplyId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult getList(Integer pageSize, String search_str,Integer pageNum, Integer apply_type, String userId) {
        if (isNullOrEmpty(apply_type)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsCarUseApplicationResp> respList = new ArrayList<>();
        int total = 0;
        if (apply_type == CAR_USE_TYPE_APPLY) {

            Page<SmsCarUseApplication> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsCarUseApplication> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsCarUseApplication::getApplyUserId, userId)
                    .orderByDesc(SmsCarUseApplication::getCreateTime);
            if(!isNullOrEmpty(search_str)){
                queryWrapper.lambda().like(SmsCarUseApplication::getApplyDepartment,search_str);
            }
            smsCarUseApplicationMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsCarUseApplication -> {
                        SmsCarUseApplicationResp smsCarUseApplicationResp =
                                new SmsCarUseApplicationResp();
                        BeanUtils.copyProperties(smsCarUseApplication, smsCarUseApplicationResp);
                        smsCarUseApplicationResp.setApplicationId(smsCarUseApplication.getId());

                        SmsUser smsUser = cacheUtil.getUserInfo(smsCarUseApplication.getApplyUserId());
                        SmsCarUseApplicationUserResp smsCarUseApplicationUserResp = new SmsCarUseApplicationUserResp();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, smsCarUseApplicationUserResp);
                        }
                        smsCarUseApplicationResp.setApplyUserInfo(smsCarUseApplicationUserResp);


                        return smsCarUseApplicationResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == CAR_USE_TYPE_ALLOWED) {
            Page<SmsCarUseApplicationMPJResp> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsCarUseApplicationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsCarUseApplicationDetail.class)
                    .selectAll(SmsCarUseApplication.class)
                    .selectAs(SmsCarUseApplication::getCreateTime, "createTime")
                    .selectAs(SmsCarUseApplicationDetail::getId, "detailId")
                    .leftJoin(SmsCarUseApplication.class, SmsCarUseApplication::getId, SmsCarUseApplicationDetail::getApplicationId)
                    .eq(SmsCarUseApplicationDetail::getDetailAllowUserId, userId)
                    .orderByDesc(SmsCarUseApplicationDetail::getDetailAllowTime)
            ;
            mpjLambdaWrapper.and(wrapper -> {
                wrapper.eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_PASS)
                        .or()
                        .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_DENY);
            });
            if(!isNullOrEmpty(search_str)){
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, search_str))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());

                mpjLambdaWrapper.and(q ->{
                    q.like(SmsCarUseApplication::getApplyDepartment,search_str);
                    if(userIds.size() > 0) {
                        q.or().in(SmsCarUseApplication::getApplyUserId, userIds);
                    }
                });
            }
            smsCarUseApplicationMpjMapper.selectJoinPage(page, SmsCarUseApplicationMPJResp.class, mpjLambdaWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsCarUseMPJResp -> {
                        SmsCarUseApplicationResp smsCarUseApplicationResp = new SmsCarUseApplicationResp();
                        BeanUtils.copyProperties(smsCarUseMPJResp, smsCarUseApplicationResp);
                        smsCarUseApplicationResp.setCreateTime(smsCarUseMPJResp.getCreateTime());

                        SmsUser applyUser = cacheUtil.getUserInfo(smsCarUseApplicationResp.getApplyUserId());
                        SmsCarUseApplicationUserResp smsCarUseApplicationUserResp = new SmsCarUseApplicationUserResp();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, smsCarUseApplicationUserResp);
                        }
                        smsCarUseApplicationResp.setApplyUserInfo(smsCarUseApplicationUserResp);

                        SmsUser allowUser = cacheUtil.getUserInfo(smsCarUseApplicationResp.getDetailAllowUserId());
                        SmsCarUseApplicationUserResp smsApplicationAllowUserResp = new SmsCarUseApplicationUserResp();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, smsApplicationAllowUserResp);
                        }
                        smsCarUseApplicationResp.setAllowUserInfo(smsApplicationAllowUserResp);

                        return smsCarUseApplicationResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == CAR_USE_TYPE_ALLOW_WAIT_ME) {
            List<String> roleList = cacheUtil.getRoleList(userId);

            //获取所有待审批申请流程节点
            List<SmsCarUseApplicationDetail> allDetailList =
                    smsCarUseApplicationDetailMapper.selectList(new QueryWrapper<SmsCarUseApplicationDetail>()
                            .lambda()
                            .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_WAIT_ALLOW));

            List<SmsCarUseApplicationDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessIsApplicationEdit().equals(1)) {
                            if (!detail.getProcessObjectId().equals(userId)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessObjectType() == CAR_USE_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessObjectId().equals(userId)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }


                        if (detail.getDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsCarUseApplicationDetail preDetail =
                                smsCarUseApplicationDetailMapper.selectOne(new QueryWrapper<SmsCarUseApplicationDetail>()
                                        .lambda()
                                        .eq(SmsCarUseApplicationDetail::getApplicationId, detail.getApplicationId())
                                        .eq(SmsCarUseApplicationDetail::getDetailSort, detail.getDetailSort() - 1)
                                        .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsCarUseApplicationDetail::getId).collect(Collectors.toList());

                Page<SmsCarUseApplicationMPJResp> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsCarUseApplicationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsCarUseApplicationDetail.class)
                        .selectAll(SmsCarUseApplication.class)
                        .selectAs(SmsCarUseApplication::getCreateTime, "createTime")
                        .selectAs(SmsCarUseApplicationDetail::getId, "detailId")
                        .leftJoin(SmsCarUseApplication.class, SmsCarUseApplication::getId, SmsCarUseApplicationDetail::getApplicationId)
                        .in(SmsCarUseApplicationDetail::getId, detailIDList)
                        .orderByDesc(SmsCarUseApplication::getCreateTime)
                        .orderByDesc(SmsCarUseApplicationDetail::getDetailAllowTime)
                ;

                if(!isNullOrEmpty(search_str)){
                    List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                            .lambda()
                            .like(SmsUser::getRealName, search_str))
                            .stream()
                            .map(SmsUser::getId).collect(Collectors.toList());

                    mpjLambdaWrapper.and(q ->{
                        q.like(SmsCarUseApplication::getApplyDepartment,search_str);
                        if(userIds.size() > 0) {
                            q.or().in(SmsCarUseApplication::getApplyUserId, userIds);
                        }
                    });
                }
                smsCarUseApplicationMpjMapper.selectJoinPage(page, SmsCarUseApplicationMPJResp.class, mpjLambdaWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsApplicationMPJResp -> {
                            SmsCarUseApplicationResp smsApplicationResp = new SmsCarUseApplicationResp();
                            BeanUtils.copyProperties(smsApplicationMPJResp, smsApplicationResp);
                            smsApplicationResp.setApplicationId(smsApplicationMPJResp.getApplicationId());
                            smsApplicationResp.setCreateTime(smsApplicationMPJResp.getCreateTime());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsApplicationResp.getApplyUserId());
                            SmsCarUseApplicationUserResp smsApplicationUserResp = new SmsCarUseApplicationUserResp();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, smsApplicationUserResp);
                            }
                            smsApplicationResp.setApplyUserInfo(smsApplicationUserResp);

                            return smsApplicationResp;
                        })
                        .collect(Collectors.toList());
                total = (int) page.getTotal();

            }
        }
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult getDetail(String apply_id, String userId) {
        if (isNullOrEmpty(apply_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsCarUseApplication smsCarUseApplication = smsCarUseApplicationMapper.selectById(apply_id);
        if (smsCarUseApplication == null || isNullOrEmpty(smsCarUseApplication.getId())) {
            return CommonResult.failed(CommonCodeEnum.CAR_USE_NOT_EXIST);
        }

        SmsCarUseApplicationResp smsCarUseApplicationResp = new SmsCarUseApplicationResp();
        BeanUtils.copyProperties(smsCarUseApplication, smsCarUseApplicationResp);
//        QueryWrapper<SmsCarWarehousing> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().eq(SmsCarWarehousing::getId,smsCarUseApplicationResp.getCarId());
//        if(isNullOrEmpty(queryWrapper)){
//            return CommonResult.failed(CommonCodeEnum.DATA_NOT_FOUND);
//        }
//        SmsCarWarehousing warehousing = smsCarWarehousingMapper.selectOne(queryWrapper);
//        smsCarUseApplicationResp.setCarName(warehousing.getCarName());
//        smsCarUseApplicationResp.setCarPic(warehousing.getCarPic());
//        smsCarUseApplicationResp.setCarPosition(warehousing.getCarPosition());
//        smsCarUseApplicationResp.setCarPower(warehousing.getCarPower());
//        smsCarUseApplicationResp.setCarVin(warehousing.getCarVin());
//        smsCarUseApplicationResp.setCarOperatingMode(warehousing.getCarOperatingMode());
//        smsCarUseApplicationResp.setCarNum(warehousing.getCarNum());
        smsCarUseApplicationResp.setApplicationId(smsCarUseApplication.getId());
        SmsUser smsUser = cacheUtil.getUserInfo(smsCarUseApplicationResp.getApplyUserId());
        SmsCarUseApplicationUserResp smsCarUseApplicationUserResp = new SmsCarUseApplicationUserResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsCarUseApplicationUserResp);
        }
        smsCarUseApplicationResp.setApplyUserInfo(smsCarUseApplicationUserResp);

        List<SmsCarUseApplicationDetailResp> detailRespList =
                smsCarUseApplicationDetailMapper.selectList(new QueryWrapper<SmsCarUseApplicationDetail>()
                        .lambda()
                        .eq(SmsCarUseApplicationDetail::getApplicationId, apply_id)
                        .orderByAsc(SmsCarUseApplicationDetail::getDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsCarUseApplicationDetailResp detailResp = new SmsCarUseApplicationDetailResp();
                            BeanUtils.copyProperties(detail, detailResp);
                            if (detailResp.getProcessObjectType() == CAR_USE_OBJECT_TYPE_PERSON) {
                                SmsUser smsUser1 = smsUserMapper.selectById(detailResp.getProcessObjectId());
                                detailResp.setRealName(smsUser1.getRealName());
                                detailResp.setHeadPic(smsUser1.getUserPic());
                            } else if (detailResp.getProcessObjectType() == CAR_USE_OBJECT_TYPE_ROLE) {
                                SmsRole smsRole = smsRoleMapper.selectById(detailResp.getProcessObjectId());
                                detailResp.setRealName(smsRole.getRoleName());
                            }

                            if (!isNullOrEmpty(detailResp.getDetailAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getDetailAllowUserId());
                                SmsCarUseApplicationUserResp applicationUserDTO = new SmsCarUseApplicationUserResp();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, applicationUserDTO);
                                }
                                detailResp.setAllowUserInfo(applicationUserDTO);
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        smsCarUseApplicationResp.setDetailList(detailRespList);

        return CommonResult.success(smsCarUseApplicationResp);
    }

    @Transactional
    @Override
    public ResponseResult allowApplication(SmsCarUseApplicationAllowReq allowVO, String user_id) {
        if (isNullOrEmpty(allowVO.getApplyId()) || isNullOrEmpty(allowVO.getDetailId())
                || isNullOrEmpty(allowVO.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowVO.getDetailAllowStatus() != CAR_USE_STATUS_PASS
                && allowVO.getDetailAllowStatus() != CAR_USE_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsCarUseApplicationDetail applicationDetail =
                smsCarUseApplicationDetailMapper.selectOne(new QueryWrapper<SmsCarUseApplicationDetail>()
                        .lambda()
                        .eq(SmsCarUseApplicationDetail::getApplicationId, allowVO.getApplyId())
                        .eq(SmsCarUseApplicationDetail::getId, allowVO.getDetailId())
                        .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_WAIT_ALLOW));
        if (isNullOrEmpty(applicationDetail)) {
            return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止调节点审批）
        if (applicationDetail.getProcessObjectType() == CAR_USE_OBJECT_TYPE_PERSON) {
            if (!applicationDetail.getProcessObjectId().equals(user_id)) {
                return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(user_id);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(applicationDetail.getProcessObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_FAIL);
            }
        }
        if (!applicationDetail.getDetailSort().equals(1)) {
            SmsCarUseApplicationDetail preDetail =
                    smsCarUseApplicationDetailMapper.selectOne(new QueryWrapper<SmsCarUseApplicationDetail>()
                            .lambda()
                            .eq(SmsCarUseApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsCarUseApplicationDetail::getDetailSort, applicationDetail.getDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != CAR_USE_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.CAR_USE_ALLOW_FAIL);
                }
            }
        }

        SmsCarUseApplicationDetail allowDetail = new SmsCarUseApplicationDetail();
        allowDetail.setId(allowVO.getDetailId());
        allowDetail.setDetailAllowStatus(allowVO.getDetailAllowStatus());
        if (!isNullOrEmpty(allowVO.getDetailAllowOption())) {
            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOption());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(user_id);

        if (applicationDetail.getProcessIsSign()) {
            if (isNullOrEmpty(allowVO.getDetailAllowSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
        }
        if (applicationDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(allowVO.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowStamp(allowVO.getDetailAllowStamp());
        }
//        if(!isNullOrEmpty(allowVO.getDetailAllowOption())){
//            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOption());
//        }

        smsCarUseApplicationDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsCarUseApplicationDetailMapper.selectCount(new QueryWrapper<SmsCarUseApplicationDetail>()
                .lambda()
                .eq(SmsCarUseApplicationDetail::getApplicationId, allowVO.getApplyId()));
        if (detailCount.equals(applicationDetail.getDetailSort()) || allowVO.getDetailAllowStatus() == CAR_USE_STATUS_DENY) {
            is_done = true;

            SmsCarUseApplication updateApplication = new SmsCarUseApplication();
            updateApplication.setId(allowVO.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowVO.getDetailAllowStatus());
            smsCarUseApplicationMapper.updateById(updateApplication);
        }
//        if (detailCount.equals(applicationDetail.getDetailSort()) && allowVO.getDetailAllowStatus() == CAR_USE_STATUS_PASS) {
//            SmsCarUseApplication smsCarUseApplication = smsCarUseApplicationMapper.selectById(allowVO.getApplyId());
//            smsCarUseApplication.setIsReturn(0);
//            smsCarUseApplicationMapper.updateById(smsCarUseApplication);
//            QueryWrapper<SmsCarWarehousing> queryWrapper = new QueryWrapper<>();
//            queryWrapper.lambda().eq(SmsCarWarehousing::getCarStatus, CAR_STATUS_IN)
//                    .eq(SmsCarWarehousing::getId, smsCarUseApplication.getCarId());
//            SmsCarWarehousing smsCarWarehousing = smsCarWarehousingMapper.selectOne(queryWrapper);
//                smsCarWarehousing.setCarStatus(CAR_STATUS_OUT);
//                smsCarWarehousingMapper.updateById(smsCarWarehousing);
//        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == CAR_USE_STATUS_DENY) {
            SmsCarUseApplicationDetail updateDenyDetail =
                    new SmsCarUseApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(CAR_USE_STATUS_DENY_FINISH);
            smsCarUseApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsCarUseApplicationDetail>()
                    .lambda()
                    .eq(SmsCarUseApplicationDetail::getApplicationId, allowVO.getApplyId())
                    .eq(SmsCarUseApplicationDetail::getDetailAllowStatus, CAR_USE_STATUS_WAIT_ALLOW));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowVO.getDetailAllowStatus() == CAR_USE_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowVO.getApplyId(), user_id, result_status);
        } else {
            SmsCarUseApplicationDetail nextDetail =
                    smsCarUseApplicationDetailMapper.selectOne(new QueryWrapper<SmsCarUseApplicationDetail>()
                            .lambda()
                            .eq(SmsCarUseApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsCarUseApplicationDetail::getDetailSort, applicationDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessIsApplicationEdit().equals(1)) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessObjectType() == CAR_USE_OBJECT_TYPE_ROLE) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowVO.getApplyId(),
                    user_id,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult selectByTime(String useStartTime, String useEndTime) {

        if(isNullOrEmpty(useStartTime)||isNullOrEmpty(useEndTime)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        Date bgDate = TimeUtil.StringtoDate(useStartTime);
        Date endDate = TimeUtil.StringtoDate(useEndTime);

        if(bgDate.compareTo(new Date())<0||bgDate.compareTo(endDate)>0){
            return CommonResult.failed(CommonCodeEnum.CAR_USE_TIME_ILLEGAL);
        }
        List<SmsCarWarehousing> list = smsCarWarehousingMapper.selectList(null);

        Iterator<SmsCarWarehousing> iterator = list.iterator();
        while (iterator.hasNext()) {
            SmsCarWarehousing warehousing = iterator.next();
            //获取到库存每一条数据，再根据时间段查询没有时间交集的所有车辆
            QueryWrapper<SmsCarUseApplication> wrapper = new QueryWrapper<>();
            //时间冲突
            wrapper.lambda()
                    .eq(SmsCarUseApplication::getCarId, warehousing.getId())
                    .eq(SmsCarUseApplication::getAllowStatus, 1)
                    .not(qw -> qw.le(SmsCarUseApplication::getUseEndTime, useStartTime)
                            .or().ge(SmsCarUseApplication::getUseStartTime, useEndTime))
                    .and(query ->{
                        query.ne(SmsCarUseApplication::getIsReturn, 1)
                                .or()
                                .isNull(SmsCarUseApplication::getIsReturn);
                    });
            Integer count1 = smsCarUseApplicationMapper.selectCount(wrapper);
            if (count1 > 0) {
                iterator.remove();
            }
        }


//            QueryWrapper<SmsCarUseApplication> wrapper = new QueryWrapper<>();
//            wrapper.lambda()
//                    //.ne(SmsCarUseApplication::getIsReturn, 1)
//                    .eq(SmsCarUseApplication::getAllowStatus,1)
//                    .eq(SmsCarUseApplication::getCarId, warehousing.getId());
//
//            Integer count = smsCarUseApplicationMapper.selectCount(wrapper);
//            if (count == 0) {
//                newList.add(warehousing);
//            } else {

//                if (useStartTime != null && useEndTime != null) {
//                    //时间不冲突
//                    wrapper.lambda().and(qw -> qw.le(SmsCarUseApplication::getUseEndTime, useStartTime)
//                            .or().ge(SmsCarUseApplication::getUseStartTime, useEndTime));
//
//                    Integer count1 = smsCarUseApplicationMapper.selectCount(wrapper);
//
//                    //时间冲突
//                    QueryWrapper<SmsCarUseApplication> queryWrapper1 = new QueryWrapper<>();
//                    queryWrapper1.lambda()
//                            .eq(SmsCarUseApplication::getAllowStatus,1)
//                            .eq(SmsCarUseApplication::getCarId, warehousing.getId())
//                            .not(qw -> qw.le(SmsCarUseApplication::getUseEndTime, useStartTime)
//                                    .or().ge(SmsCarUseApplication::getUseStartTime, useEndTime));
//                    Integer count2 = smsCarUseApplicationMapper.selectCount(queryWrapper1);
//                    List<SmsCarUseApplication> list1 = smsCarUseApplicationMapper.selectList(queryWrapper1);
////                    if(list1.isEmpty()){
////                        return CommonResult.success(newList);
////                    }
//                    for(SmsCarUseApplication application : list1){
//                        SmsCarWarehousing warehousing1 = smsCarWarehousingMapper.selectById(application.getCarId());
//                        if ((count2>0&&warehousing1.getCarStatus()==1)) {
//                            newList.add(warehousing);
//                            break;
////&&warehousing.getCarStatus()==1
//                        }
//                    }
//                    if(count1>0){
//                        newList.add(warehousing);
//                    }
//
//                } else {
//                    newList.add(warehousing);
//                }
//            }
//        }

        return CommonResult.success(list);
    }

    @Override
    public ResponseResult getCarUseApplicationOriginSettingProcess() {
        List<SmsCarUseApplicationOriginSettingProcessResp> respList =
                smsCarUseApplicationProcessMapper.selectList(new QueryWrapper<SmsCarUseApplicationProcess>()
                        .lambda()
                        .eq(SmsCarUseApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsCarUseApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsCarUseApplicationProcess::getProcessSort))
                        .stream()
                        .map(process -> {
                            SmsCarUseApplicationOriginSettingProcessResp smsCarUseOriginSettingProcessResp =
                                    new SmsCarUseApplicationOriginSettingProcessResp();
                            BeanUtils.copyProperties(process, smsCarUseOriginSettingProcessResp);
                            return smsCarUseOriginSettingProcessResp;
                        })
                        .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult selectAllCarUseApply(String apply_unit, Integer pageSize, Integer pageNum) {
        QueryWrapper<SmsCarUseApplication> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(apply_unit)) {
            queryWrapper.lambda().like(SmsCarUseApplication::getApplyDepartment, apply_unit);
        }
        queryWrapper.orderByDesc("create_time");
        Page<SmsCarUseApplication> page = new Page<>(pageNum, pageSize);
        List<SmsCarUseApplicationResp> collect;

        Page<SmsCarUseApplication> appApplicationPage = smsCarUseApplicationMapper.selectPage(page, queryWrapper);
        List<SmsCarUseApplication> records = appApplicationPage.getRecords();
        collect = records.stream().map(appApplication -> {
            SmsCarUseApplicationResp appApplicationResp = new SmsCarUseApplicationResp();
            BeanUtils.copyProperties(appApplication, appApplicationResp);
            appApplicationResp.setApplicationId(appApplication.getId());
            SmsUser smsUser = cacheUtil.getUserInfo(appApplicationResp.getApplyUserId());
            if (smsUser != null) {
                SmsCarUseApplicationUserResp user = new SmsCarUseApplicationUserResp();
                BeanUtils.copyProperties(smsUser, user);
                appApplicationResp.setApplyUserInfo(user);
            }

            return appApplicationResp;
        }).collect(Collectors.toList());

        int total = (int) page.getTotal();
        return CommonResult.success(collect, total);
    }

    @Override
    public Future<ResponseResult> tableDownload(String apply_id, HttpServletResponse response) {
        return null;
    }

    @Override
    public Future<ResponseResult> exportCarUseApplication(SmsCarUseApplicationExportReq exportReq, HttpServletResponse response) {
        return null;
    }


}
